//by:undead 2019-05-30 15:17:26
Vue.component("z-calendar", {
    template: `<div class="zCalendar">
        <div class= "top_row">
            <div id="idCalendarPre" class="calenderArrow icon-prev" @click='preMonth'></div>
            <div id="idCalendarNext" class="calenderArrow icon-next" @click='nextMonth'></div>
            <span id="idCalendarYear">{{year}}</span>年
            <span id="idCalendarMonth">{{month}}</span>月
            <input type="checkbox" @click='selectWeeks($event,-1)' ref='checkbox0' v-if='this.isMultiSelect && !this.isHotelSelect'>
        </div>
        <table class="data-picker" >
            <thead>
                <tr>
                    <th>日<input type="checkbox" @click='selectWeeks($event,0)' ref='checkbox7' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>一<input type="checkbox" @click='selectWeeks($event,1)' ref='checkbox6' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>二<input type="checkbox" @click='selectWeeks($event,2)' ref='checkbox5' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>三<input type="checkbox" @click='selectWeeks($event,3)' ref='checkbox4' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>四<input type="checkbox" @click='selectWeeks($event,4)' ref='checkbox3' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>五<input type="checkbox" @click='selectWeeks($event,5)' ref='checkbox2' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                    <th>六<input type="checkbox" @click='selectWeeks($event,6)' ref='checkbox1' v-if='this.isMultiSelect && !this.isHotelSelect'></th>
                </tr>
            </thead>
        <tbody id="idCalendar">
            <tr v-for="i in Math.round(dateArray.length / 7)" >
                <td v-for="(item,index) in dateArray.slice((i-1)*7,i*7)"
                    :class=" {
                              'normal': item.isDateValidity,
                              'checked': item.isChecked,
                              //'startTime': item.isStartTime,
                              //'endTime': item.isEndTime,
                            } "
                    @dblclick.stop="onDblClick(item)"
                    @click="onClickDate(item)">
                    <span :id="'day'+item.d" v-if="item.d != 0">
                        {{item.d}}
                    </span>
                    <template v-for="data in dataArray"  v-if="data.price && (item.d != 0 && isDateConsistent(item.date, data.date) )">
                    <em v-if="!item.isEndTime  && item.isDateValidity  && data.price>=0">
                        {{currency}}{{data.price}}
                       <template v-if="isSmallPrice">起</template>
                    </em>
                    </template>
                    <span class="startTime" v-if='item.isStartTime'>入住</span>
                    <span class="endTime" v-if='item.isEndTime'>离店</span>
                </td>
            </tr>
        </tbody>
        </table>
    </div>`,
    data: function data() {
        return {
            debug: true,
            renderQuantity: 0,
            localTime: new Date(),
            year: 0,
            month: 0,
            currency: "￥", //货比符号
            globalDateArray: [], //记录全局的日期组
            dateArray: [],
            dateModel: {
                y: 2019,
                m: 1,
                d: 1,
                date: new Date(),
                isDateValidity: true, //是否超过当前有效期
                isChecked: false, //是否选中
                isStartTime: false, //是否属于酒店选中的开始日期
                isEndTime: false //是否属于酒店选中的结束日期
            },
            hotelInfo: {
                startTime: undefined,
                endTime: undefined,
            },
            //对外
            isDefaultFill: false, //是否默认填充数据
            isClearChooseData: false, //每次初始化日期时时候清除已选的数据
            isUseDelete: false, //是否启用删除按钮
            isMultiSelect: true, //是否允许多选
            isHotelSelect: true, //是否开启酒店选项（入住-离店）
            isSmallPrice:false,//是否显示“起”
            onFinish: function () { },  //加载完毕后的回调函数
            onClick: function () { }, //点击日期后的回调函数
            onClickAll: function () { }, //点击周后的回调函数
            onHotelEnd: function () { }, //选择完毕酒店结束日期后的回调函数
            dataArray: [], //外部传进来的数据
            initMonth: 1, //初始化几个月份
        };
    },
    props: {
        year: {
            default: new Date().getFullYear(),
            type: Number
        },
        month: {
            default: new Date().getMonth() + 1,
            type: Number
        },
        isDefaultFill: {
            default: false,
            type: Boolean
        },
        isClearChooseData: {
            default: false,
            type: Boolean
        },
        isMultiSelect: {
            default: true,
            type: Boolean
        },
        isHotelSelect: {
            default: false,
            type: Boolean
        },
        isSmallPrice:{
            default: false,
            type: Boolean
        },
        initMonth: {
            default: 1,
            type: Number
        },
        dataArray: {
            default: [],
            type: Array
        },
        onFinish: {
            default: function () { },
            type: Function
        },
        onClick: {
            default: function () { },
            type: Function
        },
        onClickAll: {
            default: function () { },
            type: Function
        },
        onHotelEnd: {
            default: function () { },
            type: Function
        },
    },
    methods: {
        preMonth: function () { //上一月
            if (this.month <= 1) {
                this.month = 12;
                this.year--;
            } else {
                this.month -= 1;
            }
            this.$emit("date-change", this.year, this.month);
        },
        nextMonth: function () { //下一月
            if (this.month >= 12) {
                this.month = 1
                this.year++;
            } else {
                this.month += 1;
            }
            this.$emit("date-change", this.year, this.month);
        },
        isDateValidity: function (d1) { //是否超过今天有效日期
            var d2 = new Date(this.localTime.getFullYear()
                , this.localTime.getMonth()
                , this.localTime.getDate());

            return d2 <= d1;
        },
        isDateConsistent: function (d1, date) { //判断和数据的日期是否一致
            if(date.indexOf('-') == -1){
                date = date.replace(/\//g, '-')
            }
            var dateSplit = date.split("-");
            if (dateSplit.length <= 2) {
                console.error("日期格式错误！格式为：yyyy-MM-dd");
                return false;
            }
            var d2 = new Date(dateSplit[0], dateSplit[1] - 1, dateSplit[2]);

            return (d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate());
        },
        generateDate: function (year, month, mandatoryRefresh) { //初始化天数
            var _ = this;

            //去全局日期查询一下是否有，没有再生成新的
            var days = _.globalDateArray.filter(function (item) {
                return item.y == year && item.m == month;
            })[0];

            if (days && days.days && days.days.length >= 1 && !_.isClearChooseData && mandatoryRefresh != true) {
                return days.days;
            } else {
                days = [];
            }
            var firstDay = new Date(year, month - 1, 1).getDay();
            var i = 0;
            for (i = 1; i <= firstDay; i++) {
                days.push(0);
            }
            var monthDay = new Date(year, month, 0).getDate();
            for (i = 1; i <= monthDay; i++) {
                days.push(i);
            }
            for (i = 0; i < days.length % 7; i++) {
                days.push(0);
            }

            //封装时间
            var dateArray = [];
            days.forEach(function (day) {
                var model = JSON.parse(JSON.stringify(_.dateModel));
                model.y = year;
                model.m = month;
                model.d = day;
                model.date = new Date(year, month - 1, day);
                model.isDateValidity = _.isDateValidity(model.date);

                if (!_.isHotelSelect && model.d >= 1 && model.isDateValidity) { //不是酒店才允许默认选中
                    var getData = _.getDataByDate(model.date);
                    if (getData) {
                        model.isChecked = getData.isChecked || false;
                    }
                }

                dateArray.push(model);
            });

            var globalDateItem = _.globalDateArray.filter(function (item) { return item.y == year && item.m == month; })[0];
            if (globalDateItem) {
                globalDateItem.days = dateArray;
            } else {
                _.globalDateArray.push({
                    y: year,
                    m: month,
                    days: dateArray
                });
            }
            return dateArray;
        },
        getDataByDate: function (d1) { //根据日期获取数据
            var _ = this;
            var data = this.dataArray.filter(function (x) {
                return _.isDateConsistent(d1, x.date);
            })[0];
            return data;
        },
        getIndexByDate: function (d1) { //获取当前日期的下标
            var findIndex = 0;
            this.dateArray.forEach(function (item, i) {
                if (d1.getTime() == item.date.getTime() && item.d != 0) {
                    findIndex = i;
                }
            });
            return findIndex;
        },
        getDataByAroundDate: function (startTime, endTime) {//筛选出该范围日期内的所有数据
            var _ = this;
            var d1 = startTime.getTime();
            var d2 = endTime.getTime();
            
            var whereItem = this.dataArray.filter(function (item) {
                item.date = item.date.replace(/-/g, '/')
                var dateTime = new Date(item.date);
                return dateTime >= d1 && dateTime <= d2 || _.isDateConsistent(endTime, item.date);
            });


            whereItem = whereItem.sort(function (item, item2) {
                var d1 = new Date(item.date).getTime();
                var d2 = new Date(item2.date).getTime();
                return d1 - d2;
            });

            //alert(startTime + "|" + endTime+"|test:" +JSON.stringify(whereItem));

            return whereItem;
        },
        getChoseData: function () { //获取全部选中数据
            var _ = this;
            var choseData = []; //选中的数据
            _.globalDateArray.forEach(function (item) {
                item.days.forEach(function (day) {
                    if (day.isChecked) {
                        choseData.push(_.getDataByDate(day.date));
                    }
                });
            });

            var resDate = {
                dateArray: choseData,
                dateJoin: choseData.map(function (item) { return item.date; }).join(",")
            }
            return resDate;
        },
        checkAroundDate: function (startTime, endTime) {//判断选择的日期的天数是否是连贯的
            var d1 = startTime.getTime();
            var d2 = endTime.getTime();
            var day = Math.floor(Math.abs(d1 - d2) / 1000 / 60 / 60 / 24) + 1;

            return day === this.getDataByAroundDate(startTime, endTime).length;
        },
        setAllChecked: function (isBool) { //更改所有选中的状态
            this.dateArray.forEach(function (item) {
                item.isChecked = isBool || false;
            });
            this.globalDateArray.forEach(function (item) {
                item.days.forEach(function (day) {
                    day.isChecked = isBool || false;
                });
            });
        },
        clearAllTimeState: function () { //清除所有选中的状态
            this.dateArray.forEach(function (item) {
                item.isStartTime = false;
                item.isEndTime = false;
                item.isChecked = false;
            });
        },
        setHotelDate: function (item) { //设置酒店时间
            var _ = this;
            var startTime = this.hotelInfo.startTime;
            var endTime = this.hotelInfo.endTime;

            // this.clearAllTimeState();
            // item.isChecked = true;
            // if (!startTime || startTime.date > item.date){
            //     item.isStartTime = true;
            //     this.hotelInfo.startTime = item;
            // }else if(!endTime){
            //     item.isEndTime=true;
            //     this.hotelInfo.endTime = item;
            // } else if (startTime.date.getTime() == item.date.getTime() && startTime.isStartTime) {
            //     item.isStartTime = true;
            //     this.hotelInfo.startTime = null;
            //     this.hotelInfo.endTime = null;
            // } else if (startTime.date < item.date && item.date >= endTime.date){
            //     item.isStartTime = true;
            //     this.hotelInfo.startTime = item;
            // }

            if (!!startTime && !!endTime && (item.date > startTime.date || item.date < startTime.date) && item.date < endTime.date) {
                this.clearAllTimeState();
                this.hotelInfo.startTime = item;
                item.isChecked = true;
                item.isStartTime = true;
                endTime.isChecked = true;
                endTime.isEndTime = true;
            } else if (!startTime || startTime.date > item.date) {
                this.clearAllTimeState();
                this.hotelInfo.startTime = item;
                item.isChecked = true;
                item.isStartTime = true;
            }
            else if (startTime.date.getTime() == item.date.getTime() && startTime.isStartTime) {
                this.clearAllTimeState();
                this.hotelInfo.startTime = null;
                this.hotelInfo.endTime = null;
            } else if (!endTime) {
                this.hotelInfo.endTime = item;
            } else if (item.date >= endTime.date) {
                this.clearAllTimeState();
                this.hotelInfo.endTime = null;
                this.hotelInfo.startTime = item;
                item.isChecked = true;
                item.isStartTime = true;
            } else if (item.isChecked) {
                this.clearAllTimeState();
                this.hotelInfo.startTime = item;
                this.hotelInfo.startTime.isChecked = false;
                this.hotelInfo.startTime.isStartTime = false;
                this.hotelInfo.startTime.isChecked = false;
                this.hotelInfo.endTime.isEndTime = false;
                this.hotelInfo.endTime.isChecked = false;
            }

            startTime = this.hotelInfo.startTime;
            endTime = this.hotelInfo.endTime;

            var whereItems;
            if (startTime && endTime) {
                whereItems = this.getDataByAroundDate(startTime.date, endTime.date);

                if (this.checkAroundDate(startTime.date, endTime.date)) {
                    this.dateArray.forEach(function (item) {
                        whereItems.forEach(function (data) {
                            if (item.d == 0) { return false; };

                            if (_.isDateConsistent(item.date, data.date) && _.isDateConsistent(item.date, whereItems[0].date)) {
                                item.isChecked = true;
                                item.isStartTime = true;
                                // alert(item.date+"1");
                            } else if (_.isDateConsistent(item.date, data.date) && _.isDateConsistent(item.date, whereItems[whereItems.length - 1].date) && !item.isEndTime) {
                                item.isChecked = true;
                                item.isEndTime = true;
                                _.hotelInfo.endTime = item;
                                // alert(item.date + "2");

                            }
                            else if (_.isDateConsistent(item.date, data.date) && !item.isEndTime) {
                                item.isChecked = true;
                                item.isStartTime = true;
                                // alert(item.date + "3");
                            }
                        });
                    });
                }
                else {
                    this.clearAllTimeState();
                    this.hotelInfo.startTime = item;
                    this.hotelInfo.startTime.isChecked = true;
                    this.hotelInfo.startTime.isStartTime = true;
                    this.hotelInfo.endTime = null;
                }
            }

            _.checkHotelEndDate(item.date);

            //回调函数
            if (this.hotelInfo.startTime && this.hotelInfo.endTime) {
                startTime = this.hotelInfo.startTime;
                endTime = this.hotelInfo.endTime;
                whereItems = this.getDataByAroundDate(startTime.date, endTime.date);

                var last = whereItems[whereItems.length - 1];
                if (_.isDateConsistent(endTime.date, last.date)) {
                    whereItems.splice(whereItems.length - 1, 1);
                }

                this.onHotelEnd(whereItems, startTime, endTime);
            }
        },
        checkHotelEndDate: function (d1) { //检查下一天是否还有数据,没有则直接设为结束日期
            d1 = d1.toString();
            d1 = new Date(d1);
            d1.setDate(d1.getDate() + 1);

            var item = this.getDataByDate(d1);
            if (!item) {//当前选中的日期为连贯时间的最后一天
                d1.setDate(d1.getDate() - 1);
                var itemD1 = this.dateArray[this.getIndexByDate(d1)];
                if (!itemD1.isChecked || itemD1.isEndTime) { return; }
                var item = this.dateArray[this.getIndexByDate(d1) + 1];
                item.isEndTime = true;
                item.isChecked = true;
                this.hotelInfo.endTime = item;
            }
        },
        onClickDate: function (item) {
            var _ = this;
            var findItem = this.getDataByDate(item.date);

            if (item.d == 0 || !findItem || !item.isDateValidity) {
                if (this.isHotelSelect && this.hotelInfo.startTime && this.hotelInfo.startTime >= item.date){
                    var dayBefore = new Date(item.date.getTime() - 24 * 60 * 60 * 1000);
                    findItem = this.getDataByDate(dayBefore);
                    if (findItem){
                        item.isChecked = true;
                        item.isEndTime = true;
                        this.hotelInfo.endTime = item;
                        var whereItems = this.getDataByAroundDate(this.hotelInfo.startTime.date, this.hotelInfo.endTime.date)
                        this.dateArray.forEach(function (item) {
                            whereItems.forEach(function (data) {
                                if (item.d == 0) { return false; };

                                if (_.isDateConsistent(item.date, data.date)) {
                                    item.isChecked = true;
                                    item.isStartTime = true;
                                    item.isEndTime=false;
                                }
                            });
                        });
                    }
                }
                return; 
            }
            else if (item.isChecked && _.isUseDelete) { this.onClick(findItem); return; }

            if (this.isHotelSelect) {
                this.setHotelDate(item);
                this.onClick(findItem, item);
                return;
            } else if (!this.isMultiSelect) {
                this.setAllChecked(false);
            }

            if (findItem) {
                item.isChecked = !item.isChecked;
                this.onClick(findItem);
            }
        },
        onDeleteDate: function (item) { //单击删除
            item.isChecked = false;
            var findItem = this.getDataByDate(item.date);
            this.onDelete(findItem);
        },
        onDblClick: function (item) { //双击删除
            item.isChecked = !item.isChecked;
            var findItem = this.getDataByDate(item.date);
            this.onDelete(findItem);
        },
        IsExisMonth: function (month) {//判断当前月份 日期和数据日期是否一致对应
            var _ = this;
            var whereDateArray = this.dateArray.filter(function (item) {
                return item.m == month && item.d >= 1 && _.isDateValidity(item.date);
            })

            var whereDataArray = this.dataArray.filter(function (item) {
                var date = new Date(item.date);
                return (date.getMonth() + 1) == month && _.isDateValidity(date);
            });

            return whereDateArray.length == whereDataArray.length;
        },
        selectWeeks: function ($event, weeksDay) {//选择星期
            var newClick = [];//记录为勾上的数据，回传
            var _ = this;
            this.dateArray.forEach(function (item) {
                if (item.d >= 1) {
                    var day = item.date.getDay()
                    if ((day == weeksDay || weeksDay == -1) && item.isDateValidity && item.isChecked != $event.target.checked) {
                        if (!_.isDefaultFill && _.getDataByDate(item.date)) {
                            item.isChecked = $event.target.checked;
                            newClick.push(item.y + "-" + item.m + "-" + item.d);
                        } else if (_.isDefaultFill) {
                            item.isChecked = $event.target.checked;
                            newClick.push(item.y + "-" + item.m + "-" + item.d);
                        }
                    }
                }
            });
            this.onClickAll(newClick);
        },
        setDateAllOptional: function () { //设置所有日期可选,外部传进来的不做调整
            var _ = this;
            var newDateArrat = [];
            _.dateArray.forEach(function (item) {
                if (item.d >= 1 && _.isDateValidity(item.date) && !_.getDataByDate(item.date)) {
                    newDateArrat.push({
                        date: item.y + "-" + item.m + "-" + item.d,
                        price: (_.isHotelSelect ? 0 : -1)
                    });
                }
            });
            _.dataArray = _.dataArray.concat(newDateArrat);
        },
        init: function (config) {
            if (!config) { config = { mandatoryRefresh: false }; }
            if (this.renderQuantity <= 10000) { this.renderQuantity++; }
            else { console.error("渲染超过10000次，防止死循环停止初始化."); return; }

            var _ = this;
            _.dateArray = [];

            //初始化日期数据
            _.dateArray = _.dateArray.concat(this.generateDate(this.year, this.month, config.mandatoryRefresh));
            for (var i = 1; i < this.initMonth; i++) {
                _.dateArray = _.dateArray.concat(this.generateDate(this.year, (this.month + i), config.mandatoryRefresh));
            }

            //验证是否启用默认所有日历可选
            if (_.isDefaultFill) {
                if (_.dataArray.length <= 0 || !_.dataArray) {
                    _.dataArray = [];
                }
                if (!_.IsExisMonth(_.month)) {
                    if (_.debug) { console.log(this.year, this.month); }
                    _.setDateAllOptional();
                }

                //回传数据
                this.$emit("data-change", _.dataArray);
            }

            //将checkbox设置未选
            for (var index in _.$refs) {
                var item = _.$refs[index];
                if (item.getAttribute("type") == "checkbox") {
                    item.checked = false;
                }
            }

            //酒店模式下是否清空选项
            if (_.isHotelSelect && _.isClearChooseData) {
                _.hotelInfo.startTime = null;
                _.hotelInfo.endTime = null;
            }

            //初始化完毕后回调函数
            this.onFinish(_.dateArray);
        }
    },
    computed: {
    },
    watch: {
        year: function () {
            this.init();
        },
        month: function (val, oldVal) {
            this.init();
        },
        dataArray: function (val, oldVal) {
            
            if (val.length <= 0 && oldVal <= 0) { return; }
            this.init({
                mandatoryRefresh: true
            });
        }
    },
    created: function created() {
        this.init();
        console.log(this.dataArray)
    }
});
